home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / UTIL_SRC / C007.ZIP / TEXTFORM.C < prev    next >
Text File  |  1990-01-19  |  9KB  |  373 lines

  1. /********************************************************************
  2.  * C Users Group (U.K) C Source Code Library File CUGLIB.007        *
  3.  * Inquiries to: M. Houston, 36 Whetstone Clo. Farquhar Rd.         *
  4.  * Edgbaston, Birmingham B15 2QN ENGLAND                *
  5.  ********************************************************************
  6.  * File name: textform.c
  7.  * Program name: textform
  8.  * Source of file: The Public Domain Software Library.
  9.  * Purpose: Wordstar like text file formatter.
  10.  * Changes: <who what when & why major changes have been made>      
  11.  ********************************************************************/
  12.  
  13. /********************************************************
  14. *                            *
  15. *           T E X T  F O R M             *
  16. *           Text file formatter for MSDOS        *
  17. *                            *
  18. *          T. Jennings 23 Dec. 82        *
  19. *            created 14 Nov. 82        *
  20. *                            *
  21. *********************************************************
  22.  
  23.     TEXTFORM prints and/or formats edited text, using WordStar
  24. compatible dot commands, for use on non-WordStar systems. See 
  25. TEXTFORM.DOC for details. */
  26.  
  27. #include <stdio.h>
  28. #include <ctype.h>
  29.  
  30. #define FALSE 0
  31. #define TRUE 1
  32. #define ERROR -1
  33. #define CONTROLZ 0x1a
  34. #define CR 0x0d                /* useful ASCII characters */
  35. #define LF 0x0a
  36. #define FF 0x0c
  37. #define TAB 9
  38. #define BS 8
  39. #define PAGE_LEN 66            /* default lines per page */
  40. #define DEF_LMARGIN 8            /* default left margin, */
  41. #define DEF_TMARGIN 1            /* default top of page margin */
  42. #define DEF_BMARGIN 8            /* bottom of page margin */
  43.  
  44. char c;                    /* a useful variable for everyone */
  45. int line_count;                /* total lines, */
  46. int this_line;                /* current line #/page */
  47. int this_page;                /* current page */
  48. int page_size;                /* current max page length */
  49. int lmargin,rmargin;            /* current left and right margins */
  50. int top_margin;                /* lines from top of page */
  51. int bot_margin;                /* lines at bottom of page */
  52. int line_num;                /* true if line numbers in index */
  53.  
  54. int inbuf;                /* text file */
  55. int outbuf;
  56. char inname[80];            /* where we save ASCII filenames */
  57. char outname[80];
  58. char header[134];            /* top of page header */
  59. char subheader[134];            /* sub title, */
  60.  
  61. int flag;                /* user variable */
  62. int cond_flag;                /* conditional print flag */
  63.  
  64. change_page()                /* dummy function to start a new page */
  65. {}
  66. /* Process the input file. If no output is specified, write it it 
  67. the standard output. */
  68.  
  69. main(argc,argv)
  70. int argc;
  71. char *argv[];
  72. {
  73. char *p,*pp;
  74. int i;
  75. int have_file;
  76. int arg_error;
  77.  
  78.     fprintf (stderr,"TEXTFORM -- Text file Formatter (c) T. Jennings 23 Dec. 1982\n");
  79.     page_size =PAGE_LEN;
  80.     lmargin =DEF_LMARGIN;
  81.     top_margin= DEF_TMARGIN;
  82.     bot_margin= DEF_BMARGIN;
  83.     line_num= FALSE;
  84.     strcpy(header,"");            /* no header */
  85.     strcpy(subheader,"");
  86.     flag= 0;                /* flags off */
  87.     cond_flag= 1;                /* allow printing */
  88.     have_file= 0;                /* no output file yet */
  89.     arg_error= 0;                /* no error yet, */
  90.  
  91. /* Process the command line. We must have a filename, and optionally one
  92. of two options: list amount of memory, of add line numbers to the index. */
  93.  
  94.     --argc;
  95.     strcpy (inname,argv[1]);        /* get input file, */
  96.     inbuf= open(inname,0x8000);        /* try to open, */
  97.     if (inbuf == ERROR) {
  98.         fprintf(stderr,"Can't seem to find %s.\n",inname);
  99.         fprintf(stderr,"Try: TEXTFORM <file> <outfile>\n");
  100.         fprintf(stderr,"If <outfile> is omitted, output goes\n");
  101.         fprintf(stderr,"to the PRN device.\n");
  102.         exit();
  103.     }
  104.     strcpy(outname,"PRN");            /* default output file */
  105.     --argc; i= 2;
  106.     while (argc-- > 0) {
  107.         p= argv[i++];
  108.         if (*p == '-') {        /* check for options, */
  109.             ++p;            /* skip the dash, */
  110.             fprintf(stderr,"'%c' is not an option.\n",*p);
  111.             ++arg_error;
  112.         } else {
  113.             if (! have_file) {
  114.                 strcpy(outname,p);
  115.                 have_file= 1;
  116.             } else {
  117.                 fprintf(stderr,"Already have an output file!\n");
  118.                 ++arg_error;
  119.             }
  120.         }
  121.     }
  122.     if (arg_error) {
  123.         fprintf(stderr,"Too many mistakes.\n");
  124.         exit();
  125.     }
  126.     outbuf= creat(outname,0x8001);        /* open output file */
  127.     if (outbuf == ERROR) {
  128.         fprintf(stderr,"Can't make new file '%s'.\n",outname);
  129.         exit();
  130.     }
  131.     fprintf(stderr,"Printing to %s.\n",outname);
  132.     print();
  133.     wrtc(FF,outbuf);    /* final formfeed, */
  134.     close(inbuf); close(outbuf);
  135.     exit();            /* exit. */
  136. }
  137. /* Print each line to the printer, processing dot commands as we go. */
  138.  
  139. print()
  140. {
  141. char linebuf[132];        /* character line buffer */
  142. int i;
  143.  
  144.     line_count =0;
  145.     this_page =1;
  146.     this_line =0;
  147.  
  148.     while ( fill_line(linebuf) !=CONTROLZ)        /* until EOF, */
  149.     {    if (scan_line(linebuf) ==TRUE)        /* look for dot cmds */
  150.             continue;            /* get next line */
  151.         if (cond_flag == 0)
  152.             continue;            /* print if enabled */
  153.  
  154.         ++line_count;                /* count total lines,*/
  155.         if (this_line == 0) {
  156.             do_header();            /* do headers, */
  157.             i= top_margin;
  158.             wrtc(CR,outbuf); 
  159.             while (i--) {            /* do top margin, */
  160.                 wrtc(LF,outbuf);
  161.             }
  162.         }
  163.         i= lmargin;                /* do left margin, */
  164.         while (i--) {
  165.             wrtc(' ',outbuf);
  166.         }
  167.         sendstr(linebuf,outbuf);        /* print line, */
  168.  
  169.         if (this_line > (page_size- bot_margin))
  170.         {    wrtc(CR,outbuf);
  171.             while (this_line < page_size)
  172.                 wrtc(LF,outbuf);
  173.             ++this_page;
  174.             this_line= 0;
  175.         }
  176.     }
  177.     return;
  178. }
  179. /* Compare two strings, of a given length. Check only for equality. Return
  180. 0 if equal, else 1. */
  181.  
  182. compl(length,first,last)
  183. int length;
  184. char *first,*last;
  185. {
  186.  
  187.     for (; length >0; length--)
  188.     {    if (  (toupper(*first)) != (toupper(*last))  )
  189.             return (1)
  190.         ;
  191.         ++first; ++last;
  192.     }
  193.     return (0);
  194. }
  195. /* Fill a line buffer with characters. Return CONTROLZ if end of file. */
  196.  
  197. fill_line(buffer)
  198. char buffer[];
  199. {
  200. int i;
  201. char d;
  202.  
  203.     i=0;
  204.     do {    if (read(inbuf,&d,1) != 1)
  205.             return (CONTROLZ);    /* check physical end */
  206.         if (d ==CONTROLZ) {
  207.             return (d);
  208.         }
  209.         buffer[i++]= d& 0x7f;
  210.     }
  211.     while ((d !=LF) && (i <132));
  212.     buffer[i]= 0x00;            /* terminate */
  213.     return(d);
  214. }
  215. /* Scan for dot commands. When and if we find a dot command, fool the 
  216. caller into thinking that the line we were passed is now empty. (Return TRUE)
  217. If we find a formfeed, treat it the same as a .pa. */
  218.  
  219. scan_line(buffer)
  220. char *buffer;
  221. {
  222. int i;
  223. char c;
  224.     if (*buffer =='.')        /* as per WS specs, must be first atom */
  225.     {    if (compl (3,buffer,".pa") ==0)
  226.         {    wrtc(CR,outbuf);
  227.             while (this_line < page_size) {
  228.                 wrtc(LF,outbuf);
  229.             }
  230.             ++this_page;
  231.             this_line =0;
  232.  
  233.         } else if (compl (3,buffer,".pn") == 0) {
  234.             i= get_next_num(buffer);    /* get new page num, */
  235.             if (i)                /* if not zero, */
  236.                 this_page= i;        /* set it, */
  237.  
  238.         } else if (compl (3,buffer,".pl") == 0) {
  239.             i= get_next_num(buffer);    /* get new paper */
  240.             if (i > 5)            /* length, */
  241.                 page_size= i;
  242.  
  243.         } else if (compl (3,buffer,".mt") == 0) {
  244.             i= get_next_num(buffer);
  245.             if (i == 0)
  246.                 i= 1;
  247.             if (i < 40)            /* get top margin, */
  248.                 top_margin= i;        /* set if reasonable */
  249.         } else if (compl (3,buffer,".mb") == 0) {
  250.             i= get_next_num(buffer);
  251.             if (i < page_size)        /* set bottom margin */
  252.                 bot_margin= i;
  253.  
  254.         } else if (compl (3,buffer,".he") == 0) {
  255.             while (isgraph(*buffer))    /* skip the .he, */
  256.                 ++buffer;
  257.             if (*buffer == ' ')        /* and any space, */
  258.                 ++buffer;
  259.             strcpy(header,buffer);        /* copy the header, */
  260.  
  261.         } else if (compl (3,buffer,".sh") == 0) {
  262.             while (isgraph(*buffer))
  263.                 ++buffer;        /* skip the .sh, */
  264.             if (*buffer == ' ')
  265.                 ++buffer;
  266.             strcpy(subheader,buffer);
  267.  
  268.         } else if (compl (5,buffer,".flag") == 0) {
  269.                 flag= get_next_num(buffer); /* set variable */
  270.  
  271.         } else if (compl (7,buffer,".ifflag") == 0) {
  272.                 cond_flag= flag;
  273.  
  274.         } else if (compl (6,buffer,".endif") == 0) {
  275.                 cond_flag= 1;        /* allow printing */
  276.  
  277.         } else if (compl (3,buffer,".lm") == 0) {
  278.                 i= get_next_num(buffer);
  279.                 if (i <80)
  280.                     lmargin= i;
  281.         }
  282.         return (TRUE);
  283.     }
  284.  
  285.     if (*buffer == FF) {
  286.         wrtc(FF,outbuf);
  287.         ++this_page;
  288.         this_line= 0;
  289.         return(TRUE);
  290.     }
  291.     return (FALSE);
  292. }
  293. /* Print the top of page header. If we find a #, replace it with 
  294. the current page number, and replace % with the user flag. */
  295.  
  296. do_header() {
  297.  
  298. char c;
  299. char *p;
  300. char pnum[8];
  301.  
  302.     p= header;
  303.     while (*p) {            /* look at current char, */
  304.         if (*p == '#') {
  305.             sprintf(pnum,"%d",this_page);
  306.             sendstr(pnum,outbuf);
  307.         } else if (*p == '%') {
  308.             sprintf(pnum,"%d",flag);
  309.             sendstr(pnum,outbuf);
  310.         } else
  311.             wrtc(*p,outbuf);
  312.         ++p;
  313.     }
  314.     p= subheader;
  315.     while (*p) {
  316.         if (*p == '#') {
  317.             sendstr(pnum,outbuf);
  318.             sprintf(pnum,"%d",this_page);
  319.         } else if (*p == '%') {
  320.             sprintf(pnum,"%d",flag);
  321.             sendstr(pnum,outbuf);
  322.         } else 
  323.             wrtc(*p,outbuf);
  324.         ++p;
  325.     }
  326.     return;
  327. }
  328. /* Send an ascii string to the output file */
  329.  
  330. sendstr(string)
  331. char *string;
  332. {
  333.     while (*string)
  334.     {    wrtc (*string++,outbuf);
  335.     }
  336. }
  337. /* Write a character to the file. Count LF's as lines as they go by. */
  338.  
  339. wrtc(c,file)
  340. char c;
  341. int file;
  342. {
  343.     if (iscntrl(c)) { 
  344.         switch(c) {
  345.             case LF:
  346.                 ++this_line;
  347.             case CR:
  348.             case FF:
  349.             case TAB:
  350.             case BS:
  351.                 write(file,&c,1);
  352.                 break;
  353.             default:
  354.                 break;
  355.         }
  356.     } else write(file,&c,1);
  357.  
  358.     return;
  359. }
  360. /* Find the next number in the string, return it's value, or 0 
  361. if none found. */
  362.  
  363. get_next_num(string)
  364. char *string;
  365. {
  366. int i;
  367.     while (! isdigit(*string))
  368.         ++string;        /* skip leading text, */
  369.     if (sscanf(string,"%d",&i) == 0)/* if cant convert, */
  370.         return(0);        /* return 0000 */
  371.     return(i);
  372. }
  373.